/*
 * $Id: EditorActions.java,v 1.21 2010/07/21 19:53:19 gaudenz Exp $
 * Copyright (c) 2001-2009, JGraph Ltd
 * 
 * All rights reserved.
 * 
 * See LICENSE file for license details. If you are unable to locate
 * this file please contact info (at) jgraph (dot) com.
 */
package vnetlab.ui.editor;

import java.awt.Color;
import java.awt.Component;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JColorChooser;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import org.w3c.dom.Document;
import com.mxgraph.analysis.mxDistanceCostFunction;
import com.mxgraph.analysis.mxGraphAnalysis;
import com.mxgraph.io.mxCodec;
import com.mxgraph.io.mxVdxCodec;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGraphModel;
import com.mxgraph.model.mxICell;
import com.mxgraph.model.mxIGraphModel;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.swing.mxGraphOutline;
import com.mxgraph.swing.handler.mxConnectionHandler;
import com.mxgraph.swing.util.mxGraphActions;
import com.mxgraph.swing.view.mxCellEditor;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxEventSource.mxIEventListener;
import com.mxgraph.util.mxResources;
import com.mxgraph.util.mxUtils;
import com.mxgraph.util.png.mxPngDecodeParam;
import com.mxgraph.util.png.mxPngImageDecoder;
import com.mxgraph.view.mxGraph;
import com.mxgraph.view.mxGraphSelectionModel;
import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import javax.swing.SwingWorker;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import vnetlab.elements.Element;
import vnetlab.manager.Configuration;
import vnetlab.manager.Manager;
import vnetlab.manager.Status;
import vnetlab.ui.CustomEventListner;
import vnetlab.ui.CustomGraph;
import vnetlab.virtualbox.VirtualBoxManager;
import vnetlab.xml.XmlManager;

public class EditorActions {

    public static final BasicGraphEditor getEditor(ActionEvent e) {
        if (e.getSource() instanceof Component) {
            Component component = (Component) e.getSource();

            while (component != null && !(component instanceof BasicGraphEditor)) {
                component = component.getParent();
            }

            return (BasicGraphEditor) component;
        }

        return null;
    }

    @SuppressWarnings("serial")
    public static class ToggleRulersItem extends JCheckBoxMenuItem {

        public ToggleRulersItem(final BasicGraphEditor editor, String name) {
            super(name);
            setSelected(editor.getGraphComponent().getColumnHeader() != null);

            addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    mxGraphComponent graphComponent = editor.getGraphComponent();

                    if (graphComponent.getColumnHeader() != null) {
                        graphComponent.setColumnHeader(null);
                        graphComponent.setRowHeader(null);
                    } else {
                        graphComponent.setColumnHeaderView(new EditorRuler(
                                graphComponent,
                                EditorRuler.ORIENTATION_HORIZONTAL));
                        graphComponent.setRowHeaderView(new EditorRuler(
                                graphComponent,
                                EditorRuler.ORIENTATION_VERTICAL));
                    }
                }
            });
        }
    }

    @SuppressWarnings("serial")
    public static class ToggleGridItem extends JCheckBoxMenuItem {

        public ToggleGridItem(final BasicGraphEditor editor, String name) {
            super(name);
            setSelected(true);

            addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    mxGraphComponent graphComponent = editor.getGraphComponent();
                    mxGraph graph = graphComponent.getGraph();
                    boolean enabled = !graph.isGridEnabled();

                    graph.setGridEnabled(enabled);
                    graphComponent.setGridVisible(enabled);
                    graphComponent.repaint();
                    setSelected(enabled);
                }
            });
        }
    }

    @SuppressWarnings("serial")
    public static class ToggleOutlineItem extends JCheckBoxMenuItem {

        public ToggleOutlineItem(final BasicGraphEditor editor, String name) {
            super(name);
            setSelected(true);

            addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    final mxGraphOutline outline = editor.getGraphOutline();
                    outline.setVisible(!outline.isVisible());
                    outline.revalidate();

                    SwingUtilities.invokeLater(new Runnable() {

                        public void run() {
                            if (outline.getParent() instanceof JSplitPane) {
                                if (outline.isVisible()) {
                                    ((JSplitPane) outline.getParent()).setDividerLocation(editor.getHeight() - 300);
                                    ((JSplitPane) outline.getParent()).setDividerSize(6);
                                } else {
                                    ((JSplitPane) outline.getParent()).setDividerSize(0);
                                }
                            }
                        }
                    });
                }
            });
        }
    }

    @SuppressWarnings("serial")
    public static class ExitAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            BasicGraphEditor editor = getEditor(e);

            if (editor != null) {
                editor.exit();
            }
        }
    }

    @SuppressWarnings("serial")
    public static class StylesheetAction extends AbstractAction {

        protected String stylesheet;

        public StylesheetAction(String stylesheet) {
            this.stylesheet = stylesheet;
        }

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                mxGraph graph = graphComponent.getGraph();
                mxCodec codec = new mxCodec();
                Document doc = mxUtils.loadDocument(EditorActions.class.getResource(stylesheet).toString());

                if (doc != null) {
                    codec.decode(doc.getDocumentElement(), graph.getStylesheet());
                    graph.refresh();
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class ZoomPolicyAction extends AbstractAction {

        protected int zoomPolicy;

        public ZoomPolicyAction(int zoomPolicy) {
            this.zoomPolicy = zoomPolicy;
        }

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                graphComponent.setPageVisible(true);
                graphComponent.setZoomPolicy(zoomPolicy);
            }
        }
    }

    @SuppressWarnings("serial")
    public static class GridStyleAction extends AbstractAction {

        protected int style;

        public GridStyleAction(int style) {
            this.style = style;
        }

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                graphComponent.setGridStyle(style);
                graphComponent.repaint();
            }
        }
    }

    @SuppressWarnings("serial")
    public static class GridColorAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                Color newColor = JColorChooser.showDialog(graphComponent,
                        mxResources.get("gridColor"), graphComponent.getGridColor());

                if (newColor != null) {
                    graphComponent.setGridColor(newColor);
                    graphComponent.repaint();
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class ScaleAction extends AbstractAction {

        protected double scale;

        public ScaleAction(double scale) {
            this.scale = scale;
        }

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                double scale = this.scale;

                if (scale == 0) {
                    String value = (String) JOptionPane.showInputDialog(
                            graphComponent, mxResources.get("value"),
                            mxResources.get("scale") + " (%)",
                            JOptionPane.PLAIN_MESSAGE, null, null, "");

                    if (value != null) {
                        scale = Double.parseDouble(value.replace("%", "")) / 100;
                    }
                }

                if (scale > 0) {
                    graphComponent.zoomTo(scale, graphComponent.isCenterZoom());
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class PageSetupAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                PrinterJob pj = PrinterJob.getPrinterJob();
                PageFormat format = pj.pageDialog(graphComponent.getPageFormat());

                if (format != null) {
                    graphComponent.setPageFormat(format);
                    graphComponent.zoomAndCenter();
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class PrintAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                PrinterJob pj = PrinterJob.getPrinterJob();

                if (pj.printDialog()) {
                    PageFormat pf = graphComponent.getPageFormat();
                    Paper paper = new Paper();
                    double margin = 36;
                    paper.setImageableArea(margin, margin, paper.getWidth()
                            - margin * 2, paper.getHeight() - margin * 2);
                    pf.setPaper(paper);
                    pj.setPrintable(graphComponent, pf);

                    try {
                        pj.print();
                    } catch (PrinterException e2) {
                        System.out.println(e2);
                    }
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class SaveAction extends AbstractAction {

        protected boolean showDialog;
        protected String lastDir = null;

        public SaveAction(boolean showDialog) {
            this.showDialog = showDialog;
        }


        /**
         * Saves XML+PNG format.
         */
//        protected void saveXmlPng(BasicGraphEditor editor, String filename,
//                Color bg) throws IOException {
//            mxGraphComponent graphComponent = editor.getGraphComponent();
//            mxGraph graph = graphComponent.getGraph();
//
//            // Creates the image for the PNG file
//            BufferedImage image = mxCellRenderer.createBufferedImage(graph,
//                    null, 1, bg, graphComponent.isAntiAlias(), null,
//                    graphComponent.getCanvas());
//
//            // Creates the URL-encoded XML data
//            mxCodec codec = new mxCodec();
//            String xml = URLEncoder.encode(mxUtils.getXml(codec.encode(graph.getModel())), "UTF-8");
//            mxPngEncodeParam param = mxPngEncodeParam.getDefaultEncodeParam(image);
//            param.setCompressedText(new String[]{"mxGraphModel", xml});
//
//            // Saves as a PNG file
//            FileOutputStream outputStream = new FileOutputStream(new File(
//                    filename));
//            try {
//                mxPngImageEncoder encoder = new mxPngImageEncoder(outputStream,
//                        param);
//
//                if (image != null) {
//                    encoder.encode(image);
//
//                    editor.setModified(false);
//                    editor.setCurrentFile(new File(filename));
//                } else {
//                    JOptionPane.showMessageDialog(graphComponent, mxResources.get("noImageData"));
//                }
//            } finally {
//                outputStream.close();
//            }
//        }


        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            BasicGraphEditor editor = getEditor(e);

            if (editor != null) {
                mxGraphComponent graphComponent = editor.getGraphComponent();
                mxGraph graph = graphComponent.getGraph();
                FileFilter selectedFilter = null;

                DefaultFileFilter VNetLabFilter = new DefaultFileFilter(".vnl", "VNetLab " + mxResources.get("file") + " (.vnl)");
                //DefaultFileFilter xmlPngFilter = new DefaultFileFilter(".png", "PNG+XML " + mxResources.get("file") + " (.png)");
                //FileFilter vmlFileFilter = new DefaultFileFilter(".html", "VML " + mxResources.get("file") + " (.html)");
                String filename = null;
                boolean dialogShown = false;

                if (showDialog || editor.getCurrentFile() == null) {
                    String wd;

                    if (lastDir != null) {
                        wd = lastDir;
                    } else if (editor.getCurrentFile() != null) {
                        wd = editor.getCurrentFile().getParent();
                    } else {
                        wd = System.getProperty("user.dir");
                    }

                    JFileChooser fc = new JFileChooser(wd);

                    // Adds the default file format
                    FileFilter defaultFilter = VNetLabFilter;
                    //FileFilter defaultFilter = xmlPngFilter;
                    //fc.addChoosableFileFilter(defaultFilter);

                    // Adds special vector graphics formats and HTML
                    fc.addChoosableFileFilter(VNetLabFilter);
                    //fc.addChoosableFileFilter(new DefaultFileFilter(".mxe", "mxGraph Editor " + mxResources.get("file") + " (.mxe)"));
                    //fc.addChoosableFileFilter(new DefaultFileFilter(".svg", "SVG " + mxResources.get("file") + " (.svg)"));
                    //fc.addChoosableFileFilter(vmlFileFilter);
                    //fc.addChoosableFileFilter(new DefaultFileFilter(".html", "HTML " + mxResources.get("file") + " (.html)"));

                    // Adds a filter for each supported image format
//                    Object[] imageFormats = ImageIO.getReaderFormatNames();

                    // Finds all distinct extensions
//                    HashSet<String> formats = new HashSet<String>();
//
//                    for (int i = 0; i < imageFormats.length; i++) {
//                        String ext = imageFormats[i].toString().toLowerCase();
//                        formats.add(ext);
//                    }
//
//                    imageFormats = formats.toArray();

//                    for (int i = 0; i < imageFormats.length; i++) {
//                        String ext = imageFormats[i].toString();
//                        fc.addChoosableFileFilter(new DefaultFileFilter("."+ ext, ext.toUpperCase() + " " + mxResources.get("file") + " (." + ext + ")"));
//                    }

                    // Adds filter that accepts all supported image formats
//                    fc.addChoosableFileFilter(new DefaultFileFilter.ImageFileFilter(mxResources.get("allImages")));
                    fc.setFileFilter(defaultFilter);
                    int rc = fc.showDialog(null, mxResources.get("save"));
                    dialogShown = true;

                    if (rc != JFileChooser.APPROVE_OPTION) {
                        return;
                    } else {
                        lastDir = fc.getSelectedFile().getParent();
                    }

                    filename = fc.getSelectedFile().getAbsolutePath();
                    selectedFilter = fc.getFileFilter();

                    if (selectedFilter instanceof DefaultFileFilter) {
                        String ext = ((DefaultFileFilter) selectedFilter).getExtension();

                        if (!filename.toLowerCase().endsWith(ext)) {
                            filename += ext;
                        }
                    }

                    //Cria uma pasta com o mesmo nome do projeto, para salvar dentro o arquivo
                    File toCreate = new File(filename);
                    String fullName = toCreate.getName();
                    String simpleName = fullName.substring(0, fullName.lastIndexOf("."));
                    filename = filename.replace(fullName, simpleName+File.separator+fullName);


                    if (new File(filename).exists() && JOptionPane.showConfirmDialog(graphComponent, mxResources.get("overwriteExistingFile")) != JOptionPane.YES_OPTION) {
                        return;
                    }
                    
                } else {
                        filename = editor.getCurrentFile().getAbsolutePath();
                }


                try {
                    String ext = filename.substring(filename.lastIndexOf('.') + 1);

//                    if (ext.equalsIgnoreCase("svg")) {
//                        mxUtils.writeFile(mxUtils.getXml(mxCellRenderer.createSvgDocument(graph, null, 1, null, null).getDocumentElement()), filename);
//                    } else if (selectedFilter == vmlFileFilter) {
//                        mxUtils.writeFile(mxUtils.getXml(mxCellRenderer.createVmlDocument(graph, null, 1, null, null).getDocumentElement()), filename);
//                    } else if (ext.equalsIgnoreCase("html")) {
//                        mxUtils.writeFile(mxUtils.getXml(mxCellRenderer.createHtmlDocument(graph, null, 1, null, null).getDocumentElement()), filename);
//                    } else if (ext.equalsIgnoreCase("mxe") || ext.equalsIgnoreCase("xml")) {
                    if(ext.equalsIgnoreCase("vnl")){

                        mxCodec codec = new mxCodec();
                        
                        Node node = codec.encode(graph.getModel());

                        //String xml = mxUtils.getXml(codec.encode(graph.getModel()));
                        String xml = mxUtils.getXml(node);

                        xml = XmlManager.format(xml);

                        //Cria o arquivo
                        File file = new File(filename);

                        //Cria os dirtorios necessários, caso eles não tenham sido criados ainda
                        new File(filename.replace(file.getName(), "")).mkdirs();

                        //Escreve no arquivo
                        mxUtils.writeFile(xml, filename);

                        //Seta na configuração o caminho do arquivo e do caminho das vms do projeto
                        Configuration.getInstance().setFilePath(file.getAbsolutePath());
                        
                        editor.setModified(false);
                        editor.setCurrentFile(file);
                    }
//                    else {
//                        Color bg = null;
//
//                        if ((!ext.equalsIgnoreCase("gif") && !ext.equalsIgnoreCase("png"))
//                                || JOptionPane.showConfirmDialog(
//                                graphComponent, mxResources.get("transparentBackground")) != JOptionPane.YES_OPTION) {
//                            bg = graphComponent.getBackground();
//                        }
//
//                        if (selectedFilter == xmlPngFilter || (editor.getCurrentFile() != null && ext.equalsIgnoreCase("png") && !dialogShown)) {
//                            saveXmlPng(editor, filename, bg);
//                        } else {
//                            BufferedImage image = mxCellRenderer.createBufferedImage(graph, null, 1, bg, graphComponent.isAntiAlias(), null, graphComponent.getCanvas());
//
//                            if (image != null) {
//                                ImageIO.write(image, ext, new File(filename));
//                            } else {
//                                JOptionPane.showMessageDialog(graphComponent, mxResources.get("noImageData"));
//                            }
//                        }
//                    }
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(graphComponent, ex.toString(), mxResources.get("error"), JOptionPane.ERROR_MESSAGE);
                }
            }
        }
    }

    /**
     *
     */
    @SuppressWarnings("serial")
    public static class SelectShortestPathAction extends AbstractAction {

        /**
         *
         */
        protected boolean directed;

        /**
         *
         */
        public SelectShortestPathAction(boolean directed) {
            this.directed = directed;
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                mxGraph graph = graphComponent.getGraph();
                mxIGraphModel model = graph.getModel();

                Object source = null;
                Object target = null;

                Object[] cells = graph.getSelectionCells();

                for (int i = 0; i < cells.length; i++) {
                    if (model.isVertex(cells[i])) {
                        if (source == null) {
                            source = cells[i];
                        } else if (target == null) {
                            target = cells[i];
                        }
                    }

                    if (source != null && target != null) {
                        break;
                    }
                }

                if (source != null && target != null) {
                    int steps = graph.getChildEdges(graph.getDefaultParent()).length;
                    Object[] path = mxGraphAnalysis.getInstance().getShortestPath(graph, source, target,
                            new mxDistanceCostFunction(), steps,
                            directed);
                    graph.setSelectionCells(path);
                } else {
                    JOptionPane.showMessageDialog(graphComponent, mxResources.get("noSourceAndTargetSelected"));
                }
            }
        }
    }

    /**
     *
     */
    @SuppressWarnings("serial")
    public static class SelectSpanningTreeAction extends AbstractAction {

        /**
         *
         */
        protected boolean directed;

        /**
         *
         */
        public SelectSpanningTreeAction(boolean directed) {
            this.directed = directed;
        }

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                mxGraph graph = graphComponent.getGraph();
                mxIGraphModel model = graph.getModel();

                Object parent = graph.getDefaultParent();
                Object[] cells = graph.getSelectionCells();

                for (int i = 0; i < cells.length; i++) {
                    if (model.getChildCount(cells[i]) > 0) {
                        parent = cells[i];
                        break;
                    }
                }

                Object[] v = graph.getChildVertices(parent);
                Object[] mst = mxGraphAnalysis.getInstance().getMinimumSpanningTree(graph, v,
                        new mxDistanceCostFunction(), directed);
                graph.setSelectionCells(mst);
            }
        }
    }

    /**
     *
     */
    @SuppressWarnings("serial")
    public static class ToggleDirtyAction extends AbstractAction {

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                graphComponent.showDirtyRectangle = !graphComponent.showDirtyRectangle;
            }
        }
    }

    /**
     *
     */
    @SuppressWarnings("serial")
    public static class ToggleConnectModeAction extends AbstractAction {

        /**
         *
         */
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                mxConnectionHandler handler = graphComponent.getConnectionHandler();
                handler.setHandleEnabled(!handler.isHandleEnabled());
            }
        }
    }

    /**
     *
     */
    @SuppressWarnings("serial")
    public static class ToggleCreateTargetItem extends JCheckBoxMenuItem {

        /**
         *
         */
        public ToggleCreateTargetItem(final BasicGraphEditor editor, String name) {
            super(name);
            setSelected(true);

            addActionListener(new ActionListener() {

                /**
                 *
                 */
                public void actionPerformed(ActionEvent e) {
                    mxGraphComponent graphComponent = editor.getGraphComponent();

                    if (graphComponent != null) {
                        mxConnectionHandler handler = graphComponent.getConnectionHandler();
                        handler.setCreateTarget(!handler.isCreateTarget());
                        setSelected(handler.isCreateTarget());
                    }
                }
            });
        }
    }

    @SuppressWarnings("serial")
    public static class PromptPropertyAction extends AbstractAction {

        protected Object target;
        protected String fieldname, message;

        public PromptPropertyAction(Object target, String message) {
            this(target, message, message);
        }

        public PromptPropertyAction(Object target, String message,
                String fieldname) {
            this.target = target;
            this.message = message;
            this.fieldname = fieldname;
        }

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof Component) {
                try {
                    Method getter = target.getClass().getMethod(
                            "get" + fieldname);
                    Object current = getter.invoke(target);

                    // TODO: Support other atomic types
                    if (current instanceof Integer) {
                        Method setter = target.getClass().getMethod(
                                "set" + fieldname, new Class[]{int.class});

                        String value = (String) JOptionPane.showInputDialog(
                                (Component) e.getSource(), "Value", message,
                                JOptionPane.PLAIN_MESSAGE, null, null, current);

                        if (value != null) {
                            setter.invoke(target, Integer.parseInt(value));
                        }
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }

            // Repaints the graph component
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                graphComponent.repaint();
            }
        }
    }

    @SuppressWarnings("serial")
    public static class TogglePropertyItem extends JCheckBoxMenuItem {

        public TogglePropertyItem(Object target, String name, String fieldname) {
            this(target, name, fieldname, false);
        }

        public TogglePropertyItem(Object target, String name, String fieldname,
                boolean refresh) {
            this(target, name, fieldname, refresh, null);
        }

        public TogglePropertyItem(final Object target, String name,
                final String fieldname, final boolean refresh,
                ActionListener listener) {
            super(name);

            // Since action listeners are processed last to first we add the given
            // listener here which means it will be processed after the one below
            if (listener != null) {
                addActionListener(listener);
            }

            addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    execute(target, fieldname, refresh);
                }
            });

            PropertyChangeListener propertyChangeListener = new PropertyChangeListener() {

                public void propertyChange(PropertyChangeEvent evt) {
                    if (evt.getPropertyName().equalsIgnoreCase(fieldname)) {
                        update(target, fieldname);
                    }
                }
            };

            if (target instanceof mxGraphComponent) {
                ((mxGraphComponent) target).addPropertyChangeListener(propertyChangeListener);
            } else if (target instanceof mxGraph) {
                ((mxGraph) target).addPropertyChangeListener(propertyChangeListener);
            }

            update(target, fieldname);
        }

        public void update(Object target, String fieldname) {
            if (target != null && fieldname != null) {
                try {
                    Method getter = target.getClass().getMethod(
                            "is" + fieldname);

                    if (getter != null) {
                        Object current = getter.invoke(target);

                        if (current instanceof Boolean) {
                            setSelected(((Boolean) current).booleanValue());
                        }
                    }
                } catch (Exception e) {
                    // ignore
                }
            }
        }

        public void execute(Object target, String fieldname, boolean refresh) {
            if (target != null && fieldname != null) {
                try {
                    Method getter = target.getClass().getMethod(
                            "is" + fieldname);
                    Method setter = target.getClass().getMethod(
                            "set" + fieldname, new Class[]{boolean.class});

                    Object current = getter.invoke(target);

                    if (current instanceof Boolean) {
                        boolean value = !((Boolean) current).booleanValue();
                        setter.invoke(target, value);
                        setSelected(value);
                    }

                    if (refresh) {
                        mxGraph graph = null;

                        if (target instanceof mxGraph) {
                            graph = (mxGraph) target;
                        } else if (target instanceof mxGraphComponent) {
                            graph = ((mxGraphComponent) target).getGraph();
                        }

                        graph.refresh();
                    }
                } catch (Exception e) {
                    // ignore
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class HistoryAction extends AbstractAction {

        protected boolean undo;

        public HistoryAction(boolean undo) {
            this.undo = undo;
        }

        public void actionPerformed(ActionEvent e) {
            BasicGraphEditor editor = getEditor(e);

            if (editor != null) {
                if (undo) {
                    editor.getUndoManager().undo();
                } else {
                    editor.getUndoManager().redo();
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class FontStyleAction extends AbstractAction {

        protected boolean bold;

        public FontStyleAction(boolean bold) {
            this.bold = bold;
        }

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                Component editorComponent = null;

                if (graphComponent.getCellEditor() instanceof mxCellEditor) {
                    editorComponent = ((mxCellEditor) graphComponent.getCellEditor()).getEditor();
                }

                if (editorComponent instanceof JEditorPane) {
                    JEditorPane editorPane = (JEditorPane) editorComponent;
                    int start = editorPane.getSelectionStart();
                    int ende = editorPane.getSelectionEnd();
                    String text = editorPane.getSelectedText();

                    if (text == null) {
                        text = "";
                    }

                    try {
                        HTMLEditorKit editorKit = new HTMLEditorKit();
                        HTMLDocument document = (HTMLDocument) editorPane.getDocument();
                        document.remove(start, (ende - start));
                        editorKit.insertHTML(document, start, ((bold) ? "<b>"
                                : "<i>")
                                + text + ((bold) ? "</b>" : "</i>"), 0, 0,
                                (bold) ? HTML.Tag.B : HTML.Tag.I);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }

                    editorPane.requestFocus();
                    editorPane.select(start, ende);
                } else {
                    mxIGraphModel model = graphComponent.getGraph().getModel();
                    model.beginUpdate();
                    try {
                        graphComponent.stopEditing(false);
                        graphComponent.getGraph().toggleCellStyleFlags(
                                mxConstants.STYLE_FONTSTYLE,
                                (bold) ? mxConstants.FONT_BOLD
                                : mxConstants.FONT_ITALIC);
                    } finally {
                        model.endUpdate();
                    }
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class WarningAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                Object[] cells = graphComponent.getGraph().getSelectionCells();

                if (cells != null && cells.length > 0) {
                    String warning = JOptionPane.showInputDialog(mxResources.get("enterWarningMessage"));

                    for (int i = 0; i < cells.length; i++) {
                        graphComponent.setCellWarning(cells[i], warning);
                    }
                } else {
                    JOptionPane.showMessageDialog(graphComponent, mxResources.get("noCellSelected"));
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class NewAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            BasicGraphEditor editor = getEditor(e);

            if (editor != null) {
                if (!editor.isModified()
                        || JOptionPane.showConfirmDialog(editor, mxResources.get("loseChanges")) == JOptionPane.YES_OPTION) {
                    mxGraph graph = editor.getGraphComponent().getGraph();

                    // Check modified flag and display save dialog
                    mxCell root = new mxCell();
                    root.insert(new mxCell());
                    graph.getModel().setRoot(root);
                    editor.setModified(false);
                    editor.setCurrentFile(null);
                    Manager.getInstance().clear();
                    editor.getGraphComponent().zoomAndCenter();
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class OpenAction extends AbstractAction {

        protected String lastDir;

        protected void resetEditor(BasicGraphEditor editor) {
            editor.setModified(false);
            editor.getUndoManager().clear();
            editor.getGraphComponent().zoomAndCenter();
        }

        protected void openXmlPng(BasicGraphEditor editor, File file)
                throws IOException {
            mxPngDecodeParam decodeParam = new mxPngDecodeParam();
            decodeParam.setGenerateEncodeParam(true);
            mxPngImageDecoder decoder = new mxPngImageDecoder(new FileInputStream(file), decodeParam);
            decoder.decodeAsRenderedImage();

            String[] text = decodeParam.getEncodeParam().getCompressedText();

            if (text != null) {
                for (int i = 0; i < text.length; i++) {
                    // Finds the graph model entry in the compressed text chunks
                    if (text[i].equals("mxGraphModel") && text.length > i) {
                        Document document = mxUtils.parseXml(URLDecoder.decode(
                                text[i + 1], "UTF-8"));
                        mxCodec codec = new mxCodec(document);
                        codec.decode(document.getDocumentElement(), editor.getGraphComponent().getGraph().getModel());
                        editor.setCurrentFile(file);
                        resetEditor(editor);

                        return;
                    }
                }
            }

            JOptionPane.showMessageDialog(editor, mxResources.get("imageContainsNoDiagramData"));
        }

        protected void openVdx(BasicGraphEditor editor, File file, Document document) {
            mxGraph graph = editor.getGraphComponent().getGraph();

            // Replaces file extension with .mxe
            String filename = file.getName();
            filename = filename.substring(0, filename.length() - 4) + ".mxe";

            if (new File(filename).exists() && JOptionPane.showConfirmDialog(editor, mxResources.get("overwriteExistingFile")) != JOptionPane.YES_OPTION) {
                return;
            }

            ((mxGraphModel) graph.getModel()).clear();
            mxVdxCodec.decode(document, graph);
            editor.setCurrentFile(new File(lastDir + "/" + filename));
        }

        public void actionPerformed(ActionEvent e) {
            BasicGraphEditor editor = getEditor(e);

            if (editor != null) {
                if (!editor.isModified() || JOptionPane.showConfirmDialog(editor, mxResources.get("loseChanges")) == JOptionPane.YES_OPTION) {
                    mxGraph graph = editor.getGraphComponent().getGraph();

                    if (graph != null) {
                        String wd = (lastDir != null) ? lastDir : System.getProperty("user.dir");

                        JFileChooser fc = new JFileChooser(wd);

                        // Adds file filter for supported file format
                        DefaultFileFilter defaultFilter = new DefaultFileFilter(".vnl", "VNetLab " + mxResources.get("file") + " (.vnl)");
                        fc.setFileFilter(defaultFilter);

                        int rc = fc.showDialog(null, mxResources.get("openFile"));

                        if (rc == JFileChooser.APPROVE_OPTION) {
                            lastDir = fc.getSelectedFile().getParent();

                            try {
                                    Manager.getInstance().clear();
                                    
                                    Document document = mxUtils.parseXml(mxUtils.readFile(fc.getSelectedFile().getAbsolutePath()));
                                    mxCodec codec = new mxCodec(document);
                                    codec.decode(document.getDocumentElement(), graph.getModel());

                                    //Encontra a raiz dos elementos
                                    mxICell root = ((mxCell) graph.getModel().getRoot()).getChildAt(0);

                                    //Para cada elemento filho desta raiz, inclui na topologia
                                    for(int i=0; i < root.getChildCount(); i++){
                                        CustomEventListner.addCell((mxCell) root.getChildAt(i));
                                    }

                                    editor.setCurrentFile(fc.getSelectedFile());

                                    //Seta na configuração o caminho do arquivo e do caminho das vms do projeto
                                    Configuration.getInstance().setFilePath(fc.getSelectedFile().getAbsolutePath());


                                    resetEditor(editor);
                                }
                                catch (Exception ex) {
                                   JOptionPane.showMessageDialog(editor.getGraphComponent(), ex.toString(),
                                            mxResources.get("error"),
                                            JOptionPane.ERROR_MESSAGE);
                            }
                        }
                    }
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class ToggleAction extends AbstractAction {

        protected String key;
        protected boolean defaultValue;

        public ToggleAction(String key) {
            this(key, false);
        }

        public ToggleAction(String key, boolean defaultValue) {
            this.key = key;
            this.defaultValue = defaultValue;
        }

        public void actionPerformed(ActionEvent e) {
            mxGraph graph = mxGraphActions.getGraph(e);

            if (graph != null) {
                graph.toggleCellStyles(key, defaultValue);
            }
        }
    }

    @SuppressWarnings("serial")
    public static class SetLabelPositionAction extends AbstractAction {

        protected String labelPosition, alignment;

        public SetLabelPositionAction(String labelPosition, String alignment) {
            this.labelPosition = labelPosition;
            this.alignment = alignment;
        }

        public void actionPerformed(ActionEvent e) {
            mxGraph graph = mxGraphActions.getGraph(e);

            if (graph != null && !graph.isSelectionEmpty()) {
                graph.getModel().beginUpdate();
                try {
                    // Checks the orientation of the alignment to use the
                    // correct constants
                    if (labelPosition.equals(mxConstants.ALIGN_LEFT)
                            || labelPosition.equals(mxConstants.ALIGN_CENTER)
                            || labelPosition.equals(mxConstants.ALIGN_RIGHT)) {
                        graph.setCellStyles(mxConstants.STYLE_LABEL_POSITION,
                                labelPosition);
                        graph.setCellStyles(mxConstants.STYLE_ALIGN, alignment);
                    } else {
                        graph.setCellStyles(
                                mxConstants.STYLE_VERTICAL_LABEL_POSITION,
                                labelPosition);
                        graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN,
                                alignment);
                    }
                } finally {
                    graph.getModel().endUpdate();
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class SetStyleAction extends AbstractAction {

        protected String value;

        public SetStyleAction(String value) {
            this.value = value;
        }

        public void actionPerformed(ActionEvent e) {
            mxGraph graph = mxGraphActions.getGraph(e);

            if (graph != null && !graph.isSelectionEmpty()) {
                graph.setCellStyle(value);
            }
        }
    }

    @SuppressWarnings("serial")
    public static class KeyValueAction extends AbstractAction {

        protected String key, value;

        public KeyValueAction(String key) {
            this(key, null);
        }

        public KeyValueAction(String key, String value) {
            this.key = key;
            this.value = value;
        }

        public void actionPerformed(ActionEvent e) {
            mxGraph graph = mxGraphActions.getGraph(e);

            if (graph != null && !graph.isSelectionEmpty()) {
                graph.setCellStyles(key, value);
            }
        }
    }

    @SuppressWarnings("serial")
    public static class PromptValueAction extends AbstractAction {

        protected String key, message;

        public PromptValueAction(String key, String message) {
            this.key = key;
            this.message = message;
        }

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof Component) {
                mxGraph graph = mxGraphActions.getGraph(e);

                if (graph != null && !graph.isSelectionEmpty()) {
                    String value = (String) JOptionPane.showInputDialog(
                            (Component) e.getSource(),
                            mxResources.get("value"), message,
                            JOptionPane.PLAIN_MESSAGE, null, null, "");

                    if (value != null) {
                        if (value.equals(mxConstants.NONE)) {
                            value = null;
                        }

                        graph.setCellStyles(key, value);
                    }
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class AlignCellsAction extends AbstractAction {

        protected String align;

        public AlignCellsAction(String align) {
            this.align = align;
        }

        public void actionPerformed(ActionEvent e) {
            mxGraph graph = mxGraphActions.getGraph(e);

            if (graph != null && !graph.isSelectionEmpty()) {
                graph.alignCells(align);
            }
        }
    }

    @SuppressWarnings("serial")
    public static class AutosizeAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            mxGraph graph = mxGraphActions.getGraph(e);

            if (graph != null && !graph.isSelectionEmpty()) {
                Object[] cells = graph.getSelectionCells();
                mxIGraphModel model = graph.getModel();

                model.beginUpdate();
                try {
                    for (int i = 0; i < cells.length; i++) {
                        graph.updateCellSize(cells[i]);
                    }
                } finally {
                    model.endUpdate();
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class ColorAction extends AbstractAction {

        protected String name, key;

        public ColorAction(String name, String key) {
            this.name = name;
            this.key = key;
        }

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                mxGraph graph = graphComponent.getGraph();

                if (!graph.isSelectionEmpty()) {
                    Color newColor = JColorChooser.showDialog(graphComponent,
                            name, null);

                    if (newColor != null) {
                        graph.setCellStyles(key, mxUtils.hexString(newColor));
                    }
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class BackgroundImageAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                String value = (String) JOptionPane.showInputDialog(
                        graphComponent, mxResources.get("backgroundImage"),
                        "URL", JOptionPane.PLAIN_MESSAGE, null, null,
                        "http://www.callatecs.com/images/background2.JPG");

                if (value != null) {
                    if (value.length() == 0) {
                        graphComponent.setBackgroundImage(null);
                    } else {
                        Image background = mxUtils.loadImage(value);
                        // Incorrect URLs will result in no image.
                        // TODO provide feedback that the URL is not correct
                        if (background != null) {
                            graphComponent.setBackgroundImage(new ImageIcon(
                                    background));
                        }
                    }

                    // Forces a repaint of the outline
                    graphComponent.getGraph().repaint();
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class BackgroundAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                Color newColor = JColorChooser.showDialog(graphComponent,
                        mxResources.get("background"), null);

                if (newColor != null) {
                    graphComponent.getViewport().setOpaque(false);
                    graphComponent.setBackground(newColor);
                }
                // Forces a repaint of the outline
                graphComponent.getGraph().repaint();
            }
        }
    }

    @SuppressWarnings("serial")
    public static class PageBackgroundAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                Color newColor = JColorChooser.showDialog(graphComponent,
                        mxResources.get("pageBackground"), null);

                if (newColor != null) {
                    graphComponent.setPageBackgroundColor(newColor);
                }

                // Forces a repaint of the component
                graphComponent.repaint();
            }
        }
    }

    @SuppressWarnings("serial")
    public static class StyleAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof mxGraphComponent) {
                mxGraphComponent graphComponent = (mxGraphComponent) e.getSource();
                mxGraph graph = graphComponent.getGraph();
                String initial = graph.getModel().getStyle(
                        graph.getSelectionCell());
                String value = (String) JOptionPane.showInputDialog(
                        graphComponent, mxResources.get("style"), mxResources.get("style"), JOptionPane.PLAIN_MESSAGE, null,
                        null, initial);

                if (value != null) {
                    graph.setCellStyle(value);
                }
            }
        }
    }

    @SuppressWarnings("serial")
    public static class ExecuteAction extends AbstractAction {

        public void actionPerformed(final ActionEvent e) {
            
            final BasicGraphEditor editor = getEditor(e);

            while(editor.getCurrentFile() == null){

                int response = JOptionPane.showConfirmDialog(editor, "Save the project before running it. Want to save it now?");

                if(response == JOptionPane.YES_OPTION){
                    new SaveAction(false).actionPerformed(e);
                }
                else{
                    return;
                }
            }

            editor.setModified(true);
            editor.showProgressBar(true);

            new SwingWorker<Void, Void>() {
                @Override
                protected Void doInBackground() throws Exception {

                    //Configura as pasta onde iram ficar os hds e as maquinas virtuais
                    editor.setProgressBarLabel("Modifying Virtual Box folders...");
                    VirtualBoxManager.getInstance().modifyVirtualBoxFolders();

                    Element element = null;

                    try {
                        VirtualBoxManager manager = VirtualBoxManager.getInstance();

                        for (Element e : Manager.getInstance().getMap().values()) {

                            element = e;

                            if (element != null && !element.getType().equals("Switch")) {

                                final String nome = element.getName();
                                final String template = element.getTemplate();
                                final int nroInterfaces = element.getInterfaces().length;
                                //Se não foi criado, então cria a maquina virtual
                                if (!element.isCreated()) {

                                    editor.setProgressBarLabel("Creating element " + nome + "...");
                                    manager.create(nome, template, nroInterfaces);
                                    element.setCreated(true);
                                }
                                //Se conseguiu criar, então executa a maquina virtual
                                if (element.isCreated()) {
                                    //Estabelece as conexões
                                    for (int k = 0; k < nroInterfaces; k++) {
                                        if (element.getConectedType(k).equals("Switch")) {
                                            manager.connectVM2Switch(nome, element.conectedWho(k), k + 1);
                                        }
                                        if (element.getConectedType(k).equals("Router")
                                                || element.getConectedType(k).equals("Computer")
                                                || element.getConectedType(k).equals("Server")) {
                                            manager.connectVM2VM(nome, element.conectedWho(k), k + 1);
                                        }
                                        if(!element.isConected(k)){
                                            manager.removeNetwork(nome, k+1);
                                        }
                                    }
                                    editor.setProgressBarLabel("Running element " + nome + "...");
                                    manager.run(nome);
                                    element.setStatus(Status.EXECUTE);

                                }
                            }
                        }
                        Manager.getInstance().setStatus(Status.EXECUTE);

                    } catch (InterruptedException ex) {

                        Logger.getLogger(EditorActions.class.getName()).log(Level.SEVERE, null, ex);
                        JOptionPane.showMessageDialog(null, "Could not create the element:" + element.getName());

                    }
                    new SaveAction(false).actionPerformed(e);
                    editor.showProgressBar(false);
                    return null;
                }
            }.execute();
        }
    }

    @SuppressWarnings("serial")
    public static class StopAction extends AbstractAction {

        public void actionPerformed(final ActionEvent e) {

            final BasicGraphEditor editor = getEditor(e);

            editor.setModified(true);
            editor.showProgressBar(true);

            new SwingWorker<Void, Void>() {
                @Override
                protected Void doInBackground() throws Exception {
                    editor.setProgressBarLabel("Stopping all virtual machines");
                    VirtualBoxManager.getInstance().stopAll();
                    Manager.getInstance().setStatus(Status.STOP);
                    new SaveAction(false).actionPerformed(e);
                    editor.showProgressBar(false);
                    return null;
                }
            }.execute();
        }
    }

    @SuppressWarnings("serial")
    public static class ResumeAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            VirtualBoxManager manager = VirtualBoxManager.getInstance();
            mxCell c = (mxCell) getEditor(e).getGraphComponent().getGraph().getSelectionCell();
            Element element =  Manager.getInstance().getElement(Integer.toString(Integer.parseInt(c.getId())));
            String name = element.getName();
            manager.resume(name);
            element.setStatus(Status.EXECUTE);
            getEditor(e).setModified(true);
        }
    }

    @SuppressWarnings("serial")
    public static class PauseAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            VirtualBoxManager manager = VirtualBoxManager.getInstance();
            mxCell c = (mxCell) getEditor(e).getGraphComponent().getGraph().getSelectionCell();
            Element element =  Manager.getInstance().getElement(Integer.toString(Integer.parseInt(c.getId())));
            String name = element.getName();
            manager.pause(name);
            element.setStatus(Status.PAUSE);
        }
    }

    @SuppressWarnings("serial")
    public static class ShowTerminalAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            VirtualBoxManager manager = VirtualBoxManager.getInstance();
            mxCell c = (mxCell) getEditor(e).getGraphComponent().getGraph().getSelectionCell();
             Element element = Manager.getInstance().getElement(Integer.toString(Integer.parseInt(c.getId())));
            String nome = element.getName();
            manager.show(nome);
            element.setTerminalOpened(true);
        }
    }

    @SuppressWarnings("serial")
    public static class HideTerminalAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {
            VirtualBoxManager manager = VirtualBoxManager.getInstance();
            mxCell c = (mxCell) getEditor(e).getGraphComponent().getGraph().getSelectionCell();
            Element element = Manager.getInstance().getElement(Integer.toString(Integer.parseInt(c.getId())));
            String nome = element.getName();
            manager.hide(nome);
            element.setTerminalOpened(false);
        }
    }

    @SuppressWarnings("serial")
    public static class EditAction extends AbstractAction implements mxIEventListener {

        public void actionPerformed(ActionEvent e) {

            BasicGraphEditor editor = getEditor(e);
            Manager manager = Manager.getInstance();
            mxCell cell = (mxCell) editor.getGraphComponent().getGraph().getSelectionCell();
            Element element = manager.getElement(cell.getId());

            if (element != null) {
                editor.setElementToEdit(element);
            }
        }

        public void invoke(Object o, mxEventObject eo) {

            if(eo.getName().equalsIgnoreCase("change")){
                mxGraphSelectionModel selection = (mxGraphSelectionModel)o;
                CustomGraph graph = (CustomGraph)selection.getEventSource();

                mxCell cell = (mxCell)selection.getCell();
                
                if(cell != null){
                    Element element = Manager.getInstance().getElement(cell.getId());


                    if(element != null){
                        BasicGraphEditor.setElementToEdit(element);
                    }
                }
            }
        }
    }


    @SuppressWarnings("serial")
    public static class ConfigureFoldersAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {

           EditorFolderChooser directory = new EditorFolderChooser(null, true);

           do {
                directory.setVisible(true);

                if(directory.getReturnStatus() == EditorFolderChooser.RET_OK){
                    if(directory.getVBoxManageDirectory() != null)
                        Configuration.getInstance().setvBoxManagePath(directory.getVBoxManageDirectory());

                    if(directory.getTemplatesDirectory()!= null)
                        Configuration.getInstance().setTemplatesPath(directory.getTemplatesDirectory());

                    Configuration.getInstance().store();
                }
           }
           while(Configuration.getInstance().getVBoxManagePath() == null || Configuration.getInstance().getTemplatesPath() == null);
        }
    }

    @SuppressWarnings("serial")
    public static class ConfigureTemplatesAction extends AbstractAction {

        public void actionPerformed(ActionEvent e) {

           EditorTemplatesChooser chooser = new EditorTemplatesChooser(null, true);

           do {
                chooser.setVisible(true);

                if(chooser.getReturnStatus() == EditorFolderChooser.RET_OK){
                    if(chooser.getRouterTemplate() != null)
                        Configuration.getInstance().setRouterTemplate(chooser.getRouterTemplate() );

                    if(chooser.getComputerTemplate()!= null)
                        Configuration.getInstance().setComputerTemplate(chooser.getComputerTemplate());

                    if(chooser.getServerTemplate()!= null)
                        Configuration.getInstance().setServerTemplate(chooser.getServerTemplate());

                    Configuration.getInstance().store();
                }
           }
           while(Configuration.getInstance().getVBoxManagePath() == null || Configuration.getInstance().getTemplatesPath() == null);
        }
    }
}

       
